import { DomService, WebCmdService, EventEditorService } from '@farris/designer-services';
import { cloneDeep } from 'lodash-es';
import { actions, mapItem } from './interface';
import { DgControl } from './dg-control';

export class EventsEditorFuncUtils {
    constructor() { }


    /** 初始传入值 */
    static formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList, switchEvents?: (propertyData, eventList) => {}) {
        const componentLists = this.getcomponentLists(domService, viewModelId);
        const commandList = webCmdService.generateInternalCommandList();
        const allComponentList = eventEditorService.allComponentList && eventEditorService.allComponentList(domService);
        let viewModelDisplay = webCmdService.viewModelDisplay();
        let properties = [
            {
                propertyID: viewModelId,
                propertyType: 'events',
                /** 内置构件显示的命令列表 */
                internalCommandList: commandList,
                /** (事件设定)可绑定事件默认列表; */
                events: eventList,
                /** 已绑定的事件（拼接已有的参数值，拼接当前事件->待集成-从dom结构中取值，事件及对应的字符串） */
                boundEventsList: webCmdService.findParamtersPosition(propertyData, eventList, viewModelId, allComponentList),
                /** 视图模型已有命令 */
                viewModel: viewModelDisplay,
                /** 目标组件对应的所有可选的组件 */
                componentLists: componentLists,
                /** 所有组件列表 */
                allComponentList: allComponentList,
                /** 接收this.formBasicService.formMetaBasicInfo.relativePath */
                relativePath: formBasicService.formMetaBasicInfo.relativePath,
                /** 接收this.formBasicService.envType */
                envType: formBasicService.envType,
                /** 初始为空，用于存储用户点击「导入新命令」的控制器值 */
                newController: [],
                isAddControllerMethod: false,
                /** 开关控制类按钮的回调函数 */
                getEventList: () => EventsEditorFuncUtils.refreshEventsAndCommandList(webCmdService, propertyData, commandList, eventList, switchEvents),
                /** 获取事件的路径 */
                getEventPath: () => eventEditorService.getEventPath(propertyData.id, viewModelId, webCmdService),
            },
        ];
        return properties;
    }

    /** 事件编辑器传出值处理 */
    static saveRelatedParameters(eventEditorService: EventEditorService, domService: DomService, webCmdService: WebCmdService, propertyData: any, viewModelId: string, eventList, parameters: any) {
        if (parameters.isAddControllerMethod) {

            if (!parameters.controlInfo && propertyData.type) {
                parameters.controlInfo = { type: propertyData.type, name: DgControl[propertyData.type] && DgControl[propertyData.type].name };
            }

            webCmdService.addControllerMethod(propertyData, viewModelId, parameters);
            return;
        }

        /** 根据返回值整合为actions结构 */
        let actions = this.formActionsStructure(eventEditorService, propertyData, parameters);
        /** 增删改组件dom中事件绑定值 */
        this.eventsValueChanged(propertyData, actions, eventList, domService);
        /** 更新dom中的actions节点 */
        let domActions = cloneDeep(this.domActionsChanged(domService, actions));
        /** 更新dom中viewModel的绑定值 */
        webCmdService.viewModelDomChanged(propertyData, eventList, viewModelId, domActions);
        /** 删除viewModel中冗余的命令 */
        if (parameters['preCommand'] != undefined) {
            // 将preCommand中的命令与action节点的命令相比较，若action节点中不存在，则在视图模型中删除
            this.delViewModelCommand(domService, parameters, domActions);
        }
        /** 更新dom中的webcmds节点 */
        this.domWebcmdChanged(domService, parameters);
        /** 更新函数中获取到的webcmds*/
        this.functionWebcmdsChanged(webCmdService, parameters);
        /** 存在重复被使用的「已绑定命令」，则更新actions节点 */
        if (parameters['repititionCommand']) {
            this.repititionCommandExist(domService, parameters, propertyData);
        }
    }

    /** 目标组件规则判定 */
    static getcomponentLists(domService, viewModelId) {
        const dom = domService.getDomJson();
        let componentListsItem = {
            componentId: '',
            viewModelId: ''
        }
        let componentLists = [];
        let curComponent = 0;
        for (let i = 0; i < dom.module.components.length; i++) {
            //筛选出root-component及form类型的component
            if (dom.module.components[i].componentType != 'Frame' && !dom.module.components[i].componentType.includes('form')) {
                componentListsItem.componentId = cloneDeep(dom.module.components[i].id);
                componentListsItem.viewModelId = cloneDeep(dom.module.viewmodels[i].id);
                componentLists.push(cloneDeep(componentListsItem));
            }
            if (viewModelId == dom.module.viewmodels[i].id) {
                curComponent = i;
            }
        }
        //当前组件是否为root-component及form类型的component
        if (viewModelId == dom.module.viewmodels[curComponent].id) {
            if (dom.module.components[curComponent].componentType != 'Frame') {
                componentLists = [];
            }
        }
        return componentLists;
    }

    /** 根据返回值整合为actions结构 */
    static formActionsStructure(eventEditorService, data, parameters) {
        let actions: actions = {
            sourceComponent: {
                id: data.id,
                viewModelId: cloneDeep(parameters.viewModelId),
                map: []
            }
        };
        parameters.boundEventsList.forEach(boundEventItem => {
            let mapItem: mapItem = {
                event: {
                    label: boundEventItem.boundEvents.label,
                    name: boundEventItem.boundEvents.name,
                },
                targetComponent: cloneDeep(eventEditorService.formTargetComponent(boundEventItem, parameters.viewModelId)),
                command: {
                    id: boundEventItem.controllerList.id,
                    label: boundEventItem.controllerList.label,
                    name: boundEventItem.controllerList.name,
                    handlerName: boundEventItem.controllerList.handlerName,
                    params: cloneDeep(boundEventItem.controllerList.property),
                    isNewGenerated: boundEventItem.controllerList.isNewGenerated || false,
                    isRTCmd: boundEventItem.controllerList['isRTCmd'],
                    isInvalid: boundEventItem.controllerList.isInvalid || false,
                },
                controller: {
                    id: boundEventItem.controllerName.id,
                    label: boundEventItem.controllerName.label,
                    name: boundEventItem.controllerName.name,
                }
            }
            if (boundEventItem.controllerList['targetComponent']) {
                mapItem.targetComponent.id = boundEventItem.controllerList.targetComponent;
            }
            if (mapItem.targetComponent.viewModelId != undefined) {
                actions.sourceComponent.map.push(cloneDeep(mapItem));
            }
        });
        return actions;
    }
    /** 增删改组件dom中事件绑定值 */
    static eventsValueChanged(data, actions, eventList, domService) {
        //增加或修改：data[事件id] = 'viewModelId.targetComponent-viewModelId.command';
        actions.sourceComponent.map.forEach(mapItem => {
            //判断是存储为三段path或一段path
            if (mapItem.targetComponent.viewModelId && (actions.sourceComponent.viewModelId != mapItem.targetComponent.viewModelId)) {
                data[mapItem.event.label] = cloneDeep(`root-viewmodel.${mapItem.targetComponent.viewModelId}.${mapItem.command.label}`);
            } else {
                data[mapItem.event.label] = cloneDeep(`${mapItem.command.label}`);
            }
        })
        /** 删除 data[事件id] = null */
        eventList.forEach(event => {
            let exist = actions.sourceComponent.map.find(mapItem => mapItem.event.label == event.label)
            if (!exist) {
                data[event.label] = null;
                this.delActionItem(data.id, event.label, domService);
            }
        })
    }
    /** 更新dom中的acions节点 */
    static domActionsChanged(domService, actions) {
        if (actions.sourceComponent.map.length) {
            if (domService.module.actions == undefined) {
                domService.module.actions = [];
                domService.module.actions.push(cloneDeep(actions));
            }
            else {
                let domActions = domService.module.actions;
                let actionExist = false;
                //判断是否存在源组件id
                domActions.forEach(domActionItem => {
                    if (actions.sourceComponent.id == domActionItem.sourceComponent.id) {
                        actionExist = true;
                        //若存在相同源组件，则判断是否存在同一个事件id
                        actions.sourceComponent.map.forEach(mapItem => {
                            let eventExist = false;
                            domActionItem.sourceComponent.map.forEach(function (domMapItem, index) {
                                //存储过该事件，覆盖
                                if (mapItem.event.label == domMapItem.event.label) {
                                    domActionItem.sourceComponent.map[index] = cloneDeep(mapItem);
                                    eventExist = true;
                                }
                            });
                            //没有存储该事件，则增加
                            if (!eventExist) {
                                domActionItem.sourceComponent.map.push(cloneDeep(mapItem));
                            }
                        })
                    }
                })
                if (!actionExist) {
                    domActions.push(cloneDeep(actions));
                }
                domService.module.actions = cloneDeep(domActions);
            }
        }
        let domActions = cloneDeep(domService.module.actions);
        return domActions;
    }
    /** 删除viewModel中冗余的命令 */
    static delViewModelCommand(domService, parameters, domActions) {
        let preCommandExist = false;
        let targetComponent;
        domActions.forEach(domActionsItem => {
            domActionsItem.sourceComponent.map.forEach(mapItem => {
                if (mapItem.command.id == parameters.preCommand.id && mapItem.command.label == parameters.preCommand.label) {
                    preCommandExist = true;
                    targetComponent = mapItem.targetComponent.viewModelId;
                }
            })
        });
        //该命令没有被任何事件绑定，且该命令是事件面板内置的命令，则删除
        if (!preCommandExist) {
            const viewModelcommand = cloneDeep(domService.module.viewmodels)
            viewModelcommand.forEach(vmItem => {
                vmItem.commands.forEach((vmCommandsItem, index) => {
                    if (parameters.preCommand.isNewGenerated && vmCommandsItem.id == parameters.preCommand.id && vmCommandsItem.code == parameters.preCommand.label) {
                        const isDeclared = domService.module['declarations'] ? this.checkIfDelViewModelCommand(domService, vmCommandsItem) : false;
                        if (!isDeclared) { vmItem.commands.splice(index, 1) }
                    }
                });
            });
            domService.module.viewmodels = cloneDeep(viewModelcommand);
        }
    }
    /** 检测是否在组件声明中声明过该命令,若有声明，则不删除 */
    static checkIfDelViewModelCommand(domService, vmCommandsItem) {
        const declarations = domService.module.declarations;
        // root-viewmodel.data-grid-component-viewmodel.loadCard1;
        let i = 0;
        while (i < declarations.commands.length) {
            const command = declarations.commands[i].command;
            i++;
            if (vmCommandsItem.code == command) {
                return true;
            }
        }
        return false;
    }
    /** 更新dom中的webcmds节点 */
    static domWebcmdChanged(domService, parameters) {
        if (domService.module.webcmds == undefined) {
            domService.module.webcmds = [];
        }

        const relativePath = parameters.relativePath;
        let webcmds = domService.module.webcmds;
        if (parameters.boundEventsList) {
            parameters.boundEventsList.forEach(boundEventListItem => {
                let command = {
                    host: boundEventListItem.controllerList.id,
                    handler: boundEventListItem.controllerList.handlerName,
                }
                let exist = false;
                webcmds.forEach(webcmdsItem => {
                    //已经存储过该控制器
                    if (webcmdsItem.id == boundEventListItem.controllerName.id) {
                        exist = true;
                        let commandExist = -1;
                        if (webcmdsItem.refedHandlers) {
                            commandExist = webcmdsItem.refedHandlers.findIndex(commandItem =>
                                command.host == commandItem.host)
                        }
                        if (!webcmdsItem.refedHandlers) {
                            webcmdsItem['refedHandlers'] = [];
                            webcmdsItem.refedHandlers.push(cloneDeep(command));
                        }
                        if (commandExist == -1) {
                            webcmdsItem.refedHandlers.push(cloneDeep(command));
                        }
                    }
                })
                //没有存储过该控制器
                if (!exist && boundEventListItem.controllerName.label) {
                    let content = {
                        id: boundEventListItem.controllerName.id,
                        path: relativePath,
                        name: `${boundEventListItem.controllerName.label}.webcmd`,
                        refedHandlers: [],
                        // 控制器code和nameSpace；
                        // code:'',
                        // nameSpace:'',
                    }
                    content.refedHandlers.push(cloneDeep(command));
                    webcmds.push(cloneDeep(content));
                }
            })
            domService.module.webcmds = cloneDeep(webcmds);
        }
        domService.module.webcmds = cloneDeep(webcmds);
    }
    /** 更新函数中获取到的webcmds*/
    static functionWebcmdsChanged(webCmdService, parameters) {
        if (parameters.newController) {
            webCmdService.webCmdsChanged(parameters.newController);
        }
    }
    /** 删除事件时同时移除actions对应节点 */
    static delActionItem(id, eventLabel, domService) {
        const domActions = domService.module.actions;
        domActions.forEach(function (actionsItem, index) {
            if (actionsItem.sourceComponent.id == id) {
                actionsItem.sourceComponent.map.forEach(function (mapItem, index) {
                    if (mapItem.event.label == eventLabel) {
                        actionsItem.sourceComponent.map.splice(index, 1)
                    }
                });
            }
            if (actionsItem.sourceComponent.map.length == 0) {
                domActions.splice(index, 1)
            }
        });
        domService.module.actions = cloneDeep(domActions);
    }
    /** 存在重复被使用的「已绑定命令」，则更新actions节点 */
    static repititionCommandExist(domService, parameters, propertyData) {
        if (parameters['repititionCommand'].length != 0) {
            let actions = cloneDeep(domService.module.actions);
            const repititionCommand = cloneDeep(parameters.repititionCommand);
            repititionCommand.forEach(repititionCommandItem => {
                let copiedEventLabel;
                // 提取使用了「已绑定命令」的 事件的相关值
                parameters.boundEventsList.forEach(boundEventsListItem => {
                    copiedEventLabel = (boundEventsListItem.controllerList.id == repititionCommandItem.command.id) ? boundEventsListItem.boundEvents.label : undefined;
                })
                if (copiedEventLabel != undefined) {
                    let data;
                    actions.forEach(actionsItem => {
                        actionsItem.sourceComponent.map.forEach(mapItem => {
                            if (propertyData.id == actionsItem.sourceComponent.id && mapItem.controller.id == repititionCommandItem.controller.id && mapItem.command.id == repititionCommandItem.command.id && mapItem.event.label == copiedEventLabel) {
                                //记录 使用了「已绑定命令」的 事件的相关值
                                data = {
                                    targetComponent: mapItem.targetComponent,
                                    command: mapItem.command
                                }
                            }
                        })
                    });
                    actions.forEach(actionsItem => {
                        actionsItem.sourceComponent.map.forEach(mapItem => {
                            //更新「已绑定命令」原始数据
                            if (mapItem.command.id == repititionCommandItem.command.id && mapItem.controller.id == repititionCommandItem.controller.id && mapItem.event.label == repititionCommandItem.event.label) {
                                mapItem.targetComponent = cloneDeep(data['targetComponent']);
                                mapItem.command = cloneDeep(data['command']);
                            }
                        })
                    });
                    domService.module.actions = cloneDeep(actions);
                }
            });
        }
    }

    /** 开关控制类按钮的回调函数 */
    static refreshEventsAndCommandList(webCmdService, propertyData, commandList: any[], eventList, switchEvents?: (propertyData, eventList) => {}) {
        if (switchEvents) {
            eventList = switchEvents(propertyData, eventList);
        }
        commandList = webCmdService.generateInternalCommandList();

        return {
            internalCommandList: commandList,
            events: eventList
        };
    }

}
